﻿
// opencv_demo1.cpp: 定义应用程序的类行为。
//

#include "pch.h"
#include "opencv_screenshot.h"


void opencv_screenshot::start()
{
    //m_origImg = cv::imread("host.jpg");
    cv::Mat smallPic = cv::imread("host.jpg");
    cv::resize(smallPic, smallPic, cv::Size(300, 300));
   // cv::Mat host = cv::imread("host.jpg");
    cv::Mat host;
    m_origImg = getScreenshot();

    //注意格式必须相同
    cv::cvtColor(m_origImg, host, CV_BGRA2BGR);

    //贴图测试
    cv::Mat btImg1 = host(cv::Rect(20, 20, smallPic.cols, smallPic.rows));
    smallPic.copyTo(btImg1);
    cv::namedWindow("效果图");
    cv::imshow("效果图", host);

    m_origImg = getScreenshot(); 

    select.x = select.y = 0;
    while (1)
    {
        int key = cv::waitKey(10);
        switch (key)
        {
        case 's':
            cv::setMouseCallback("img", opencv_screenshot::S_on_Mouse_cb, this);
            break;
        }
        if (key == 27 || key == 'q')
            break;
    }
    cv::waitKey(0);
}

void opencv_screenshot::S_on_Mouse_cb(int event, int x, int y, int flags, void* param)//画矩形框并截图  
{
    opencv_screenshot* pthis = (opencv_screenshot*)param;
    pthis->S_on_Mouse(event,x,y,flags);
}
void opencv_screenshot::S_on_Mouse(int event, int x, int y, int flags)
{
    cv::Point p1, p2;
    switch (event)
    {
    case  cv::EVENT_LBUTTONDOWN:
    {
        printf("\n EVENT_LBUTTONDOWN");
        select.x = x;
        select.y = y;
        select_flag = true;
    }
    break;
    case cv::EVENT_MOUSEMOVE:
    {
        printf("\n EVENT_MOUSEMOVE");
        if (select_flag)
        {
            m_origImg.copyTo(showImg);
            p1 = cv::Point(select.x, select.y);
            p2 = cv::Point(x, y);
            cv::rectangle(showImg, p1, p2, cv::Scalar(0, 255, 0), 2);
            cv::imshow("img", showImg);
        }
    }
    break;
    case cv::EVENT_LBUTTONUP:
    {
        printf("\n EVENT_LBUTTONUP");
        //显示框出的ROI   
        cv::Rect roi = cv::Rect(cv::Point(select.x, select.y), cv::Point(x, y));
        if (roi.width && roi.height)
        {
            cv::namedWindow("roi", cv::WINDOW_NORMAL); //可以用户缩放窗口
            cv::Mat roiImg = m_origImg(roi);
            cv::imshow("roi", roiImg);
            cv::imwrite("screenshot.jpg", roiImg);
        }
        select_flag = false;
    }
    break;
    }
}

/* 获取整个屏幕的截图 */
cv::Mat opencv_screenshot::getScreenshot()
{
    double zoom = getZoom();
    m_width = GetSystemMetrics(SM_CXSCREEN) * zoom;
    m_height = GetSystemMetrics(SM_CYSCREEN) * zoom;
    m_screenshotData = new char[m_width * m_height * 4];
    //memset(m_screenshotData, 0, m_width);

    // 获取屏幕 DC
    m_screenDC = GetDC(NULL);
    m_compatibleDC = CreateCompatibleDC(m_screenDC);

    // 创建位图
    m_hBitmap = CreateCompatibleBitmap(m_screenDC, m_width, m_height);
    SelectObject(m_compatibleDC, m_hBitmap);

    // 得到位图的数据
    BitBlt(m_compatibleDC, 0, 0, m_width, m_height, m_screenDC, 0, 0, SRCCOPY);
    GetBitmapBits(m_hBitmap, m_width * m_height * 4, m_screenshotData);

    // 创建图像
    cv::Mat screenshot(m_height, m_width, CV_8UC4);
    memcpy(screenshot.data, m_screenshotData, m_height * m_width * 4);

    delete m_screenshotData;
    DeleteObject(m_hBitmap);
    ::DeleteDC(m_compatibleDC);
    ReleaseDC(NULL,m_screenDC);
    return screenshot;
}
/* 获取屏幕缩放值 */
double opencv_screenshot::getZoom()
{
    // 获取窗口当前显示的监视器
    HWND hWnd = GetDesktopWindow();
    HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);

    // 获取监视器逻辑宽度
    MONITORINFOEX monitorInfo;
    monitorInfo.cbSize = sizeof(monitorInfo);
    GetMonitorInfo(hMonitor, &monitorInfo);
    int cxLogical = (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left);

    // 获取监视器物理宽度
    DEVMODE dm;
    dm.dmSize = sizeof(dm);
    dm.dmDriverExtra = 0;
    EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &dm);
    int cxPhysical = dm.dmPelsWidth;

    return cxPhysical * 1.0 / cxLogical;
}